/*
 * @Author: Mr.Mao
 * @Date: 2021-05-16 12:42:29
 * @LastEditTime: 2021-06-23 23:20:31
 * @Description: 
 * @LastEditors: Mr.Mao
 * @autograph: 任何一个傻子都能写出让电脑能懂的代码，而只有好的程序员可以写出让人能看懂的代码
 */



import {
  TComplexType,
  ParamsErrorOption,
  TVerifyOption,
  VerifyType,
  IMiddleware,
  TTypeConstructors
} from './types'
import Koa from 'koa'
import { merge } from 'lodash'
import { checkVerifyItem } from './verify'

/**
 * 参数校验中间件
 * @param option 
 * @returns 中间件函数
 */
const paramsValidator = (defaultOption?: ParamsErrorOption) => async (ctx: Koa.Context, next: Koa.Next) => {
  // 深层合并默认配置
  const { messages, status } = merge({
    messages: <Record<VerifyType, string>>{
      type: '{_key_} 类型应为: {_type_}',
      regExp: '{_key_} 校验规则错误',
      required: '{_key_} 为必传项',
      intercept: '不可传入 {_key_} 字段'
    },
    status: 402
  }, defaultOption)
  /**
   * 参数统一处理
   * @param params 参数内容
   * @param option 校验配置
   */
  ctx.verifyParams = async (params: Record<string, any>, options: TVerifyOption) => {
    for (const key in options) {
      const isLiteral = options[key].constructor === Object
      const complexVerify = isLiteral ? <TComplexType>options[key] : { type: <TTypeConstructors>options[key] }
      const validator = await checkVerifyItem({ key, value: params[key], complexVerify })
      // 校验通过, 跳出当前循环
      if (validator.status) continue;
      // 错误信息
      const message = (complexVerify.message || messages[validator.validType] || '{_key_}:{_value_} 校验失败')
        .replace('{_type_}', validator.paramType)
        .replace('{_key_}', key)
      // 抛出错误
      ctx.throw(status, message)
    }
  }
  await next()
}


export default paramsValidator as (option?: ParamsErrorOption) => IMiddleware
